package com.jingdianjichi.project.domain.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.jingdianjichi.project.common.entity.PageResult;
import com.jingdianjichi.project.common.enums.IsDeletedFlagEnum;
import com.jingdianjichi.project.common.utils.LoginUtil;
import com.jingdianjichi.project.domain.bo.SubjectInfoBo;
import com.jingdianjichi.project.domain.bo.SubjectOptionBo;
import com.jingdianjichi.project.domain.convert.SubjectInfoConverter;
import com.jingdianjichi.project.domain.handler.subject.SubjectTypeHandler;
import com.jingdianjichi.project.domain.handler.subject.SubjectTypeHandlerFactory;
import com.jingdianjichi.project.domain.redis.RedisUtil;
import com.jingdianjichi.project.domain.service.SubjectInfoDomainService;
import com.jingdianjichi.project.domain.service.SubjectLikedDomainService;
import com.jingdianjichi.project.infra.basic.entity.*;
import com.jingdianjichi.project.infra.basic.service.*;
import com.jingdianjichi.project.infra.entity.UserInfo;
import com.jingdianjichi.project.infra.rpc.UserRpc;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * ClassName:SubjectCategoryDomainServiceImpl
 * Package:com.jingdianjichi.subject.domain.service.impl
 * Description:
 *
 * @Author fst
 * @Create 2024/9/26 15:39
 * @Version 1.0
 */
@Slf4j
@Service
public class SubjectInfoDomainServiceImpl implements SubjectInfoDomainService
{
    @Resource
    private SubjectInfoService subjectInfoService;

    @Resource
    private SubjectMappingService subjectMappingService;
    @Resource
    private SubjectTypeHandlerFactory subjectTypeHandlerFactory;

    @Resource
    private SubjectLabelService subjectLabelService;

    @Resource
    private SubjectEsService subjectEsService;

    @Resource
    private UserRpc userRpc;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private SubjectLikedDomainService subjectLikedDomainService;

    private static final String RANK_KEY="subject_rank";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SubjectInfoBo subjectInfoBo)
    {
        //工厂加策略的设计模式
        if(log.isInfoEnabled())
        {
            log.info("SubjectInfoDomainServiceImpl.add.BO:{}", JSON.toJSONString(subjectInfoBo));
        }

        SubjectInfo subjectInfo= SubjectInfoConverter.INSTANCE.convertBOTOInfoSubject(subjectInfoBo);

        subjectInfo.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        subjectInfoService.insert(subjectInfo);



        SubjectTypeHandler handler= subjectTypeHandlerFactory.getHandler(subjectInfo.getSubjectType());

        //主键回显
        subjectInfoBo.setId(subjectInfo.getId());
        //执行相应的策略
        handler.add(subjectInfoBo);

        List<Integer> categoryIds=subjectInfoBo.getCategoryIds();
        List<Integer> labelIds=subjectInfoBo.getLabelIds();


        List<SubjectMapping> subjectMappingList=new LinkedList<>();

        for (Integer categoryId : categoryIds) {
            for (Integer labelId : labelIds) {
                SubjectMapping subjectMapping=new SubjectMapping();

                //插入相关的对应关系
                subjectMapping.setSubjectId(subjectInfo.getId());
                subjectMapping.setCategoryId(Long.valueOf(categoryId));
                subjectMapping.setLabelId(Long.valueOf(labelId));
                subjectMapping.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
                subjectMappingList.add(subjectMapping);
            }
        }

        subjectMappingService.BatchInsert(subjectMappingList);

        //同步到es
        SubjectInfoEs subjectInfoEs=new SubjectInfoEs();

        //使用雪花算法生成自增id
        subjectInfoEs.setDocId(IdWorker.getId());

        subjectInfoEs.setSubjectId(subjectInfo.getId());

        subjectInfoEs.setSubjectAnswer(subjectInfoBo.getSubjectAnswer());

        subjectInfoEs.setCreateTime(subjectInfo.getCreatedTime());

        subjectInfoEs.setCreateUser(LoginUtil.getLoginId());

        subjectInfoEs.setSubjectName(subjectInfoBo.getSubjectName());

        subjectInfoEs.setSubjectType(subjectInfo.getSubjectType());

        subjectInfoEs.setCreateTime(new Date());

        subjectEsService.insert(subjectInfoEs);


        //把数据放入redis
        redisUtil.addScore(RANK_KEY,LoginUtil.getLoginId(),1);
    }

    /**
     * 分类查询
     * @param subjectInfoBo
     * @return
     */
    public PageResult<SubjectInfoBo> getSubjectPage(SubjectInfoBo subjectInfoBo)
    {
        PageResult<SubjectInfoBo> pageResult=new PageResult<>();
        pageResult.setPageNo(subjectInfoBo.getPageNo());
        pageResult.setPageSize(subjectInfoBo.getPageSize());

        int start= (subjectInfoBo.getPageNo()-1)* subjectInfoBo.getPageSize();

        SubjectInfo subjectInfo = SubjectInfoConverter.INSTANCE.convertBOTOInfoSubject(subjectInfoBo);


        int count=subjectInfoService.countByCondition(subjectInfo,
                subjectInfoBo.getCategoryId(),
                subjectInfoBo.getLabelId());

        log.info("total count:{} ",count);
        if(count==0)
        {
            return pageResult;
        }

       List<SubjectInfo> subjectInfoList= subjectInfoService.queryPage(subjectInfo, subjectInfoBo.getCategoryId(),
                subjectInfoBo.getLabelId(),start,subjectInfoBo.getPageSize());

        log.info("queryPage的分页查询结果：{}",subjectInfoList);

        List<SubjectInfoBo> subjectInfoBoList = SubjectInfoConverter.INSTANCE.convertInfoTOBoSubjectList(subjectInfoList);

        pageResult.setResult(subjectInfoBoList);
        pageResult.setTotal(count);


        return pageResult;
    }

    public SubjectInfoBo querySubjectInfo(SubjectInfoBo subjectInfoBo)
    {

        SubjectInfo subjectInfo = subjectInfoService.queryById(subjectInfoBo.getId());

        Integer subjectType = subjectInfo.getSubjectType();

        SubjectTypeHandler handler=subjectTypeHandlerFactory.getHandler(subjectType);

        SubjectOptionBo subjectOptionBo = handler.query(subjectInfo.getId().intValue());

        SubjectInfoBo subjectInfobo =SubjectInfoConverter.INSTANCE.convertOptionAndInfoTOBO(subjectInfo,subjectOptionBo);

        SubjectMapping subjectMapping = new SubjectMapping();
        subjectMapping.setSubjectId(subjectInfo.getId());
        subjectMapping.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        log.info("subjectMapping :{}",subjectMapping);

        List<SubjectMapping> mappingList = subjectMappingService.queryLabelId(subjectMapping);
        log.info("mappingList:{}",mappingList);

        List<Long> labelIdList = mappingList.stream().map(SubjectMapping::getLabelId).collect(Collectors.toList());

        log.info("labelIdlist:{}",labelIdList);
        List<SubjectLabel> labelList = subjectLabelService.batchQueryById(labelIdList);


        List<String> labelNameList = labelList.stream().map(SubjectLabel::getLabelName).collect(Collectors.toList());
        subjectInfobo.setLabelName(labelNameList);
        log.info("subjectInfobo:{}",subjectInfobo);



        subjectInfobo.setLiked(subjectLikedDomainService.isLiked(subjectInfoBo.getId().toString(),LoginUtil.getLoginId()));

        subjectInfobo.setLikedCount(subjectLikedDomainService.getLikedCount(subjectInfo.getId().toString()));
        assembleSubjectCursor(subjectInfobo);


        return subjectInfobo;
    }

    private  void assembleSubjectCursor(SubjectInfoBo subjectInfoBo)
    {
        Long subjectInfoBoId = subjectInfoBo.getId();

        Long categoryId = subjectInfoBo.getCategoryId();

        Long labelId = subjectInfoBo.getLabelId();

        if(categoryId==null||labelId==null) return ;

        Long  nextSubjectId = subjectInfoService.querySubjectCursor(subjectInfoBoId,categoryId,labelId,1);
        subjectInfoBo.setNextSubjectId(nextSubjectId);

        Long lastSubjectId = subjectInfoService.querySubjectCursor(subjectInfoBoId,categoryId,labelId,0);
        subjectInfoBo.setLastSubjectId(lastSubjectId);
    }

    @Override
    public PageResult<SubjectInfoEs> getSubjectPageBySearch(SubjectInfoBo subjectInfoBo)
    {

        SubjectInfoEs subjectInfoEs =new SubjectInfoEs();

        subjectInfoEs.setPageNo(subjectInfoBo.getPageNo());

        subjectInfoEs.setPageSize(subjectInfoBo.getPageSize());

        subjectInfoEs.setKeyWord(subjectInfoBo.getKeyWord());

       return  subjectEsService.querySubjectList(subjectInfoEs);

    }

    @Override
    public List<SubjectInfoBo> getContributeList() {

        Set<ZSetOperations.TypedTuple<String>> zsetList = redisUtil.rankWithScore(RANK_KEY, 0, -1);

        if(log.isInfoEnabled())
        {
            log.info("redis中获取的排行榜数据：{}",zsetList);
        }


        if(CollectionUtils.isEmpty(zsetList))
        {
            return null;
        }


//      List<SubjectInfo>  subjectInfoList= subjectInfoService.getContributeCount();

//      if(CollectionUtils.isEmpty(subjectInfoList))
//      {
//          return null;
//      }

      List<SubjectInfoBo> subjectInfoBoList= new ArrayList<>();

      zsetList.forEach(rank->{
          SubjectInfoBo subjectInfoBo=new SubjectInfoBo();

          subjectInfoBo.setSubjectCount(rank.getScore().intValue());

          UserInfo userInfo =userRpc.getUserInfo(rank.getValue());

          subjectInfoBo.setCreateUser(userInfo.getNickName());

          subjectInfoBo.setCreateUserAvatar(userInfo.getAvatar());

          subjectInfoBoList.add(subjectInfoBo);
      });
      return subjectInfoBoList;
    }
}
